package cn.biplam.common.wrapper;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 *   包含行索引和列索引的二维表
 * @author XiaoRuxing Nov 21, 200911:40:36 AM
 * @version 1.0
 */
public class D2KTable<K,M> implements Serializable{

	private static final long serialVersionUID = 8856413320386442L;

	/** 存储包含列索引的二维表 */	
	private KvMap<K,M[]> kvmTable;

	/** 存储列名称索引 */	
	private ArrayList<String> aColNameIndex;
	/** 列数 */	
	private int iColNumber;  
	/** 行数 */	
	private int iRowNumber; 

	/**
	 * 构造方法 初始化列索引
	 * @param kvmColNameIndex
	 */
	public D2KTable(ArrayList<String> aColNameIndex){
		kvmTable=new KvMap<K,M[]>();
		setColNameIndex(aColNameIndex);
		this.iRowNumber=0;
	}

	/**
	 * 添加行 如果要插入行的列数不等于对象列数抛出异常
	 * @param key            行名
	 * @param mValue         值数组
	 * @throws ErrorMessage  如果插入数组的列数不等于对象列数，抛出异常
	 */
	public void put(K key,M[] mValue) throws ErrorMessage{

		/** 如果插入数组的列数不等于对象列数，抛出异常 */
		if(mValue.length!=iColNumber){
			throw new ErrorMessage("下标越界");
		}

		kvmTable.put(key, mValue);
		
		this.iRowNumber=kvmTable.size();
	}

	/**
	 * 初始化列索引
	 * @param kvmColNameIndex
	 */
	public void setColNameIndex(ArrayList<String> aColNameIndex){

		this.aColNameIndex=aColNameIndex;
		/** 设置列数 */
		this.iColNumber=aColNameIndex.size();
	}

	/**
	 * 返回key对应的行
	 * @param key 行名
	 * @return
	 */
	public M[] get(K key){
		return kvmTable.getByKey(key);
	}

	/**
	 * 返回key对应的行中指定列
	 * @param key        行名     
	 * @param iColIndex  列序号
	 * @return 如果不存在key对应行返回空
	 * @throws ErrorMessage 如果列下标越界返回异常
	 */
	public M get(K key,int iColIndex) throws ErrorMessage{

		if(iColIndex>=this.iColNumber){
			throw new ErrorMessage("下标越界");
		}
		return kvmTable.getByKey(key)[iColIndex];
	}

	/**
	 * 返回key对应行中指定列
	 * @param key      行名
	 * @param sColName 列名
	 * @return  如果不存在key对应行返回空
	 * @throws ErrorMessage 如果列名不存在返回异常
	 */
	public M get(K key,String sColName) throws ErrorMessage{

		/** 获取列编号 */
		int colIndex=aColNameIndex.indexOf(sColName);
		/** 不存在该列返回异常 */
		if(colIndex==-1){
			throw new ErrorMessage("下标越界");
		}

		return kvmTable.getByKey(key)[colIndex];
	}

	/**
	 * 返回行数
	 * @return
	 */
	public int getRowCount(){
		return this.iRowNumber;
	}

	/**
	 * 返回列数
	 * @return
	 */
	public int getColCount(){
		return this.iColNumber;
	}

	/**
	 * 删除指定行
	 * @param key
	 */
	public void remove(K key){
		kvmTable.removeByKey(key);
	}

	/**
	 * 清空对象
	 */
	public void clear() {
		kvmTable.clear();
	}

	/**
	 * 返回列名索引
	 * @return
	 */
	public ArrayList<String> getColNameIndex(){
		return aColNameIndex;
	}
	
	/**
	 * 返回对象行迭代器
	 * @return
	 */
	public Iterator<Map.Entry<K, M[]>> getIterator(){
		return kvmTable.getIterator();
	}
	
	public boolean isNull(){
		return this.iRowNumber==0;
	}
	
	/**
	 * 返回对象的字符串表达形式
	 * @return
	 */
	public String toString(){
		
		/** 结果字符串 */
		StringBuilder sp=null;
		
		/** D2KTable对象行迭代器 */
		Iterator<Map.Entry<K,M[]>> ite=null;
		
		/** 对象行 */
		Entry<K,M[]> ent=null;

		sp=new StringBuilder();
		ite=getIterator();

		/** head */
		if(ite.hasNext()){
			ent=ite.next();
			process(sp,ent);
		}

		/** Iterator */
		while(ite.hasNext()){
			sp.append("\n");
			ent=ite.next();
			process(sp,ent);
		}

		/** bottom */
		sp.append("\n");

		return sp.toString();

	}

	private void process(StringBuilder sb,Entry<K,M[]> ent){

		M[] mCol=null;

		/** 读取行名 */
		sb.append(ent.getKey());
		sb.append("\t");

		/** 读取列数组 */
		mCol=ent.getValue();

		/** 按照列名索引读取列数据 */
		for(int i=0;i<aColNameIndex.size();i++){
			sb.append(aColNameIndex.get(i));
			sb.append("=");
			sb.append(mCol[i].toString());
			sb.append("\t");
		}

	}

}
